#include <Mutex.hh>
#include "MutexTest.hh"

Number MutexTest::Var = 0;

ResultOf MutexTest::testBasicCase(Lock* Key)
{
	ResultOf Result;
	LinkedList<pthread_t>* Root;
	
	// NOTE
	// 레이스 컨디션이 잘발생되는지 검증한다.
	// 레이스 컨디션이 발생되지 않는다면, LoopCount의 수치를 올려보기를 권한다.
	
	Var = 1234;
	
	Root = createThread(10, doInc);
	checkNullWR(Root, "Root is NULL.");
	
	Result = destoryThread(Root);
	checkErrorWR(Result, "Fail destoryThread.");
	
	if (Var == 1234 + LoopCount*10)
	{
		notifyError(Var, "Race conditions was not occur.");
		return RETURN_ERROR;
	}
	
	// NOTE
	// 이번 실험에서는 레이스 컨디션이 발생하면 안된다.
	
	Var = 1234;
	
	Root = createThread(10, doIncWithLock, Key);
	checkNullWR(Root, "Root is NULL.");
	
	Result = destoryThread(Root);
	checkErrorWR(Result, "Fail destoryThread.");
	
	if (Var != 1234 + LoopCount*10)
	{
		notifyError(Var, "Race conditions was occur.");
		return RETURN_ERROR;
	}
	
	return RETURN_OK;
}

void* MutexTest::doInc(void* Param)
{
	Param = Param;
	
	Number Temp;
	for (Number LC = 0; LC < LoopCount; LC++)
	{
		Temp  = Var;
		usleep(1);
		Var = ++Temp;
	}
	
	return NULL;
}

void* MutexTest::doIncWithLock(void* Param)
{
	Lock* Key;
	Number Temp;
	ResultOf Result;
	
	Key = (Lock*)Param;
	for (Number LC = 0; LC < LoopCount; LC++)
	{
		Result = Key->lock();
		checkErrorWOR(Result, "Fail Key->lock.");
		
		Temp = Var;
		usleep(1);
		Var = ++Temp;
		
		Result = Key->unlock();
		checkErrorWOR(Result, "Fail Key->unlock.");
	}
	
	return NULL;
}

ResultOf testMutex()
{
	Mutex Lock;
	MutexTest Test;
	ResultOf Result;
	
	Result = Test.testBasicCase(&Lock);
	if (checkError(Result))
	{
		notifyError(Result, "Fail Test.testBasicCase.");
		return RETURN_ERROR;
	}
	
	fprintf(stderr, "Mutex: Test success.\n");
	return RETURN_OK;
}
